<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"
    />
    <title>发布观察者模式</title>
</head>

<body>
    <p>提取通用观察者模式。</p>

    <div id="release">发布售楼信息</div>
    <script type="text/javascript">
        var event = {
            clientList: [],
            listen: function (key, fn) { // 订阅
                if (!this.clientList[key]) {
                    this.clientList[key] = [];
                }
                this.clientList[key].push(fn);

            },
            trigger: function () { //发布
                var key = Array.prototype.shift.call(arguments); // 取出消息类型
                var fns = this.clientList[key]; // 取出该消息对应的回调函数集合

                if (!fns || fns.length === 0) { // 如果没有订阅该消息，则返回
                    return false;
                }
                for (var i = 0, fn; fn = fns[i++];) {
                    fn.apply(this, arguments); // (2) // arguments 是发布消息时附送的参数
                }
            },
            removeListen: function (key, fn) {
                var fns = this.clientList[key];
                if (!fns) {
                    return false
                }
                if (!fn) {
                    fns && (fns.length = 0);
                } else {
                    for (var l = fns.length - 1; l >= 0; l--) { // 反向遍历订阅的回调函数列表
                        var _fn = fns[l];
                        if (_fn === fn) {
                            fns.splice(l, 1); // 删除订阅者的回调函数
                        }
                    }
                }
            }
        }

        var salesOffices = {};
        var installEvent = function (obj) {
            for (var i in event) {
                obj[i] = event[i];
            }
        };

        installEvent(salesOffices);

        salesOffices.listen('squareMeter88', fn1 = function (price) { // 小明订阅消息
            console.log('小明：价格= ' + price);
        });
        salesOffices.listen('squareMeter100', fn2 = function (price) { // 小明再次订阅消息
            console.log('小明：价格= ' + price);
        });
        salesOffices.listen('squareMeter88', fn3 = function (price) { // 小红订阅消息
            console.log('小红：价格= ' + price);
        });
        salesOffices.listen('squareMeter100', fn4 = function (price) { // 小红再次订阅消息
            console.log('小红：价格= ' + price);
        });
        salesOffices.removeListen('squareMeter88', fn1); // 删除小明的订阅

        salesOffices.trigger('squareMeter88', 2000000); // 输出：2000000
        salesOffices.trigger('squareMeter100', 3000000); // 输出：3000000


    </script>

</body>

</html>